package com.leinardi.android.speeddial;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Context;
import android.content.res.XmlResourceParser;
import android.util.AttributeSet;
import android.util.Xml;

import android.view.InflateException;

import androidx.annotation.MenuRes;

import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;

import java.io.IOException;

import timber.log.Timber;


public class MenuXmlParser {
    /** Menu tag name in XML. */
    private static final String XML_MENU = "menu";

    /** Group tag name in XML. */
    private static final String XML_GROUP = "group";

    /** Item tag name in XML. */
    private static final String XML_ITEM = "item";

    private final Context mContext;

    MenuState rootMenu;

    /**
     * Constructs a menu inflater.
     *
     * @see Activity#getMenuInflater()
     */
    public MenuXmlParser(Context context) {
        mContext = context;
    }

    /**
     * Inflate a menu hierarchy from the specified XML resource. Throws
     * {@link InflateException} if there is an error.
     *
     * @param menuRes Resource ID for an XML layout resource to load (e.g.,
     *            <code>R.menu.main_activity</code>)
     *
     */
    public void inflate(@MenuRes int menuRes) {
        try (@SuppressLint("ResourceType") XmlResourceParser parser = mContext.getResources().getLayout(menuRes)) {
            AttributeSet attrs = Xml.asAttributeSet(parser);
            rootMenu = new MenuState();
            parseMenu(parser, attrs, rootMenu);
        } catch (XmlPullParserException | IOException e) {
            throw new InflateException("Error inflating menu XML", e);
        }
    }

    /**
     * Called internally to fill the given menu. If a sub menu is seen, it will
     * call this recursively.
     */
    private void parseMenu(XmlPullParser parser, AttributeSet attrs, MenuState menu)
            throws XmlPullParserException, IOException {
        int eventType = parser.getEventType();
        String tagName;
        boolean lookingForEndOfUnknownTag = false;
        String unknownTagName = null;

        // This loop will skip to the menu start tag
        do {
            if (eventType == XmlPullParser.START_TAG) {
                tagName = parser.getName();
                if (tagName.equals(XML_MENU)) {
                    // Go to next tag
                    eventType = parser.next();
                    break;
                }

                throw new RuntimeException("Expecting menu, got " + tagName);
            }
            eventType = parser.next();
        } while (eventType != XmlPullParser.END_DOCUMENT);

        boolean reachedEndOfMenu = false;

        MenuState menuState=null;
        while (!reachedEndOfMenu) {
            switch (eventType) {
                case XmlPullParser.START_TAG:
                    if (lookingForEndOfUnknownTag) {
                        break;
                    }
                    tagName = parser.getName();
                    //Timber.d("inflater parser xml START_TAG  tagName:%s \t eventType:%d",tagName,eventType);
                    switch (tagName) {
                        case XML_GROUP:
                            /*menuState = new MenuState();  menuState.readGroup(mContext,attrs);*/
                            break;
                        case XML_ITEM:
                            menuState = new MenuState();
                            menuState.readItem(mContext,attrs);
                            menu.addGroupItem(menuState);
                            break;
                        case XML_MENU:
                            // A menu start tag denotes a submenu for an item
                           //registerMenu(subMenu, attrs);
                            menuState = new MenuState();
                            menu.addGroupItem(menuState);
                            // Parse the submenu into returned SubMenu
                            parseMenu(parser, attrs, menuState);
                            break;
                        default:
                            lookingForEndOfUnknownTag = true;
                            unknownTagName = tagName;
                            break;
                    }
                    break;

                case XmlPullParser.END_TAG:
                    tagName = parser.getName();
                    //Timber.d("inflater parser xml END_TAG  tagName:%s \t eventType:%d",tagName,eventType);
                    if (lookingForEndOfUnknownTag && tagName.equals(unknownTagName)) {
                        lookingForEndOfUnknownTag = false;
                        unknownTagName = null;
                    }  else if (tagName.equals(XML_GROUP)) {
                       /* if(menuState!=null) menuState.resetGroup();*/
                    } else if (tagName.equals(XML_ITEM)) {
                        // Add the item if it hasn't been added (if the item was
                        // a submenu, it would have been added already)
                        if (menuState!=null&&!menuState.hasAddedItem()) {
                            menu.addGroupItem(menuState);
                        }
                    } else if (tagName.equals(XML_MENU)) {
                        reachedEndOfMenu = true;
                    }
                    break;

                case XmlPullParser.END_DOCUMENT:
                    throw new RuntimeException("Unexpected end of document");
            }

            eventType = parser.next();
        }
    }
}

